import { Editor, Transforms, Element } from 'slate';
import { Plugin, PLUGINS_KEYS, EDITOR_ELEMENT_TYPE, commandType } from '../types';
import { isCollapsed, isFouceStart, isMatchKeyDown } from '@/core/utils/is';
import { getBlockMatch } from '@/core/utils/get';
import { KEYDOWNS } from '@/core/types';
import './index.less';
import { KEY_EVENT } from '../config';
import { setBlockNode, setWrapNode } from '@/core/utils/set';

const command: commandType = (editor) => {
  setBlockNode(editor, {
    [PLUGINS_KEYS.UNORDEREDLISTITEM]: { level: 1 },
  });
  setWrapNode(editor, {
    [PLUGINS_KEYS.UNORDEREDLIST]: true,
  });
};

function UnorderedList(editor: Editor): Plugin {
  return {
    key: PLUGINS_KEYS.UNORDEREDLIST,
    type: EDITOR_ELEMENT_TYPE.BLOCK,
    match: (props) => {
      return !!props.element[PLUGINS_KEYS.UNORDEREDLIST] || !!props.element[PLUGINS_KEYS.UNORDEREDLISTITEM];
    },
    command,
    render: (context) => {
      const isList = context.props.element[PLUGINS_KEYS.UNORDEREDLIST];
      const isItem = context.props.element[PLUGINS_KEYS.UNORDEREDLISTITEM];
      if (isList) {
        return <ul>{context.children}</ul>;
      } else if (isItem) {
        const level = isItem.level;
        return <li data-level={level}>{context.children}</li>;
      }
      return null;
    },
    onKeyDown: (event) => {
      if (isMatchKeyDown(event, KEYDOWNS.TAB, KEYDOWNS.ENTER, KEYDOWNS.BACKSPACE) && isCollapsed(editor)) {
        const { block, path } = getBlockMatch(editor);
        if (!block[PLUGINS_KEYS.UNORDEREDLIST] && !block[PLUGINS_KEYS.UNORDEREDLISTITEM]) return null;
        if (event.key === KEYDOWNS.TAB) {
          event.preventDefault();
          const item = block[PLUGINS_KEYS.UNORDEREDLISTITEM];
          if (!item) return;
          const { level } = item;
          if (level < 3) {
            Transforms.setNodes(editor, {
              [PLUGINS_KEYS.UNORDEREDLISTITEM]: { level: (item.level + 1) as typeof level },
            });
          }
        } else if (isFouceStart(editor, path)) {
          event.preventDefault();
          const item = block[PLUGINS_KEYS.UNORDEREDLISTITEM];
          if (!item) return;
          const { level } = item;
          if (level - 1 < 1) {
            Transforms.unsetNodes(editor, [PLUGINS_KEYS.UNORDEREDLISTITEM]);
            Transforms.unwrapNodes(editor, {
              match: (n) => {
                return !Editor.isEditor(n) && Element.isElement(n) && !!n[PLUGINS_KEYS.UNORDEREDLIST];
              },
              /**
               * 如果 split == false
               * 那 unwrap 后,剩下的子节点将也会 unwrap
               * 如果 spint == true
               * 那 unwrap 后,剩下的子节点将还在 wrap 中被包裹着
               */
              split: true,
            });
          } else {
            Transforms.setNodes(editor, {
              [PLUGINS_KEYS.UNORDEREDLISTITEM]: { level: (item.level - 1) as typeof level },
            });
          }
        }
      }
      return KEY_EVENT.Stop;
    },
  };
}

export default UnorderedList;
